/**
 * ifs-explorer.js - The main driver for the IFS Explorer
**/

// Configuration options
var config = {
	'capserver': 'http://collins.cs.ubc.ca:8080',
	'appdomain': location.protocol + '//' +  location.host,
	'appuser':   'test'
}

// The IFS capability service
var store

// The current user's IFS userid
var userid

// The current path state
var path = [] // array of caps -> reflists


// Main entry point
function ifs_explorer_main(){
	store = ifs.capservice(config.capserver + '/capsrv', 
			config.appuser, config.appdomain)
	
	store.is_logged_in( function(result){
		if(!result.data || !result.data['userid']){
			// redirect to login
			var myuserid = prompt("Enter an appuser name")
			if(!myuserid)
				myuserid = config.appuser
			
			if(confirm('You are being redirected to your '
					+'IFS provider to sign in...')){
			
				location.href = config.capserver + '/?'
					+'appuser='+ myuserid 
					+'&appdomain='+ config.appdomain
					+'&redirect='+document.location
			
			}
			
		}else{
			// user is signed in to IFS
			userid = result.data['userid']
			ifs_explorer_init()
		}
	} )	
}

// Init loads the application once an IFS session is established
function ifs_explorer_init(){

	// now store is a valid capability server session
	$('#msg').html('Welcome to <span style="font-family:\'Rationale\';font-size:1.2em">IFS Explorer</span>, ' + userid + '!')

	/*
		Use store.getns(), store.getfile(), store.getfilelist()
		and the properties of ifs.objects.Capability,
		ifs.objects.Ref, ifs.objects.Filelist to inspect
		the root namespace and data pointer and update the
		UI. See the jQuery documentation for more user
		interface tools: http://docs.jquery.com/Main_Page
	*/
	store.getns(null, {success: function(cap){
		store.getfilelist(cap, {success: function(ns){
			
			store.getptr(ns.files[1].ptr, {success: function(data){
				
				if(data != null){
					explore(btoa(data.pack())) // explore expects a stringified capability
				}else{
					// install a root directory
					var root = new ifs.objects.Filelist()
					root.meta['name'] = userid
					
					store.putfilelist(root, {success: function(own){
						//console.log(own)
						//console.log(own.pack())
						//console.log(ns.files[1].ptr)
						store.putptr(ns.files[1].ptr, own, {success: function(){
							//console.log(own)
							explore(btoa(own.pack()))
						}})
					}})
				}
			
			}})
		}})
		
	}})
}


function update_directory(newdir, parentdircap, cb){

	store.putfilelist(newdir, {success: function(newdircap){
	
		if(parentdircap == null){
			store.getns(null, {success: function(rootcap){
				store.getfilelist(rootcap, {success: function(ns){
					store.putptr(ns.files[1].ptr, newdircap, {success: function(){
						
						// callback
						cb(newdircap);
						
					}})
				}})
			}})
		}else{
	
			store.getfilelist(parentdircap, {success: function(parentdir){
				for(var i = 0; i < parentdir.files.length; i++){
					if(parentdir.files[i].meta['name'] == newdir.meta['name']){
						store.putptr(parentdir.files[i].ptr, newdircap, {success: function(){
							
							// callback
							cb(newdircap);
							
						}})
						break;
					}
				}
			}})
	
		}
	
	}})

}

// Make directories
function ifs_explorer_mkdir(){

	var dirname = prompt("Enter a folder name")
	if(!dirname)
		return alert("That is an invalid folder name!")
	
	
	var dir = new ifs.objects.Filelist()
	dir.meta['name'] = dirname
	
	store.putfilelist(dir, {success: function(dircap){
		
		store.getfilelist(path[path.length - 1].ptr, {success: function(parentdir){
			
			store.mkptr(dircap, {success: function(dirptr){
			
				parentdir.files.push({ptr: dirptr, meta: {name : dirname}})
				
				update_directory(parentdir, (path.length == 1 ? null : path[path.length - 2].ptr), function(newparentdircap){
					
					// update the path state, refresh
					path[path.length - 1] = {name: parentdir.meta['name'], ptr: newparentdircap}
					navigate_to_path(path.length - 1)
					
				})
				
			
			}})
		
		}})
	
	}})

}

// Remove directories
function ifs_explorer_rm(name, is_dir){

	if(is_dir){
		var ret = confirm("Are you sure you want to delete the \"" + name + "\" folder?") 
	}else{
		var ret = confirm("Are you sure you want to delete \"" + name + "\"?")
	}
	
	if(!ret) return;

	var newcurdir = new ifs.objects.Filelist()	

	store.getfilelist(path[path.length - 1].ptr, {success: function(curdir){
	
		newcurdir.meta['name'] = curdir.meta['name']	
		
		for(var i = 0; i < curdir.files.length; i++){
		
			if(curdir.files[i].meta['name'] != name){
				newcurdir.files.push( curdir.files[i] )
			}
			
		}
		
		update_directory(newcurdir, (path.length == 1 ? null : path[path.length - 2].ptr), function(newcurdircap){
			path[path.length - 1] = {name: curdir.meta['name'], ptr: newcurdircap}
			navigate_to_path(path.length - 1)
		})	
		
	}})

}


// Upload files
function ifs_explorer_upload(){

	if(!arguments[0]){
		$('#upload').slideToggle()
		return
	}
	
	var file = arguments[0][0]
	$('#spinner').show()
	$('#upload_type').html(file.type).show()
	$('#upload_size').html(file.size + 'B').show()
	
	store.putfile(file, {success: function(filecap){
	
		store.getfilelist(path[path.length - 1].ptr, {success: function(curdir){
		
			curdir.files.push({ptr: filecap, meta:{name: file.name, size: file.size, type: file.type}})
			
			update_directory(curdir, (path.length == 1 ? null : path[path.length - 2].ptr), function(newcurdircap){
				
				$('#spinner,#upload_type,#upload_size').hide()
				$('#upload').slideToggle()
				
				path[path.length - 1] = {name: curdir.meta['name'], ptr: newcurdircap}
				navigate_to_path(path.length - 1)
			})	
			
		}})
	
	}})

}

function explore(cap){

	function starts_with(s, p){
		return s.substring(0, p.length) == p
	}
	
	if(!cap)
		return;

	cap = new ifs.objects.Capability(atob(cap)) // cap is a stringified version initially

	var ref = cap.opts['ref']
	 
        if(starts_with(ref, "BLOB")){
         
         	display_blob(cap)
         	
        }else if(starts_with(ref, "LIST")){
         	
         	display_list(cap)
         
        }else if(starts_with(ref, "PTR")){
        
        	store.getptr(cap, {success: function(thecap){
        		if(thecap)
        			explore(btoa(thecap.pack()))
        	}})
        	
        }else{
         	display_error()
         
        }
}

function update_path(){
	
	var html = []
	
	for(var i = 0; i < path.length; i++){
		html.push( '<a href="#" class="path" onclick="navigate_to_path('+ i +')">'+
				 path[i].name +'</a>' )
	}
	
	$("#ifs_path").html(html.join(" "));
	
}


function display_error(){

	// TODO do something appropriate here
	alert("Error!")

}

function display_blob(blob_cap){
	store.getfile(blob_cap, {success: function(data){
		 	// TODO this ID must exist
		 	$("#viewer").html(data);
	}})
}

function explore_file(blob_cap, blob_meta){

	function text(cap){
		store.getfile(cap, {success: function(data){
			$('#viewer').html(data)
		}})
	}
	
	function image(cap){
		$('#viewer').html('<img src="'+ store.static_url(cap) +'"  />')
	}
	
	function pdf(cap){
		$('#viewer').html('<iframe src="'+store.static_url(cap,'application/pdf')+'" style="width:99.5%;height:98%"></iframe>')
	}
	
	function unknown(cap){
		$('#viewer').html('<b>Oops! There\'s no handler registered for this MIME type.</b>')
	}

	var handlers = {
		'text/plain': text,
		'application/javascript': text,
		'image/png': image,
		'image/gif': image,
		'image/jpeg': image,
		'application/pdf': pdf
	}

	blob_cap = new ifs.objects.Capability(atob(blob_cap))
	blob_meta = JSON.parse(atob(blob_meta))
	
	var blob_type = blob_meta['type']
	display_meta_data(blob_meta)

	if(blob_type in handlers){
		handlers[blob_type](blob_cap)
	}else{
		unknown(blob_cap)
	}

}


function navigate_to_path(idx){

	
	var ent = path[idx]
	
	path = path.slice(0, idx)
	
	display_list(ent.ptr)

}

function display_list(list_cap){
  store.getfilelist(list_cap,{success: function(list){
  
  	 
         $("#explorer").html("");
         $("#viewer").html("");
	 
	 path.push( {name: list.meta['name'], ptr: list_cap} )
	 update_path()
	 
	 
   	 display_meta_data(list.meta)
   	 $('#explorer').html( generate_list_markup(list) )
   	 
   }})
}

function generate_list_markup(list){

	function format_size(s){
		if(s < 1000)
			return s + ' B'
		if(s < 1024*1024)
			return Math.round(s/1024) + ' KB'
		if(s < (1024*1024)*1024)
			return Math.round(s/(1024*1024)) + ' MB'
		return Math.round(s/(1024*1024*1024)) + ' GB'
	}

	var html = "<table width='100%'>"
	for (i=0;i<list.files.length;i++){
		
		var is_dir = list.files[i].ptr.opts['ref'].indexOf('PTR') != -1 
		
		html += '<tr><td align="left">'
		
		if(is_dir){
			html += '<img src="images/folder.png" align="absmiddle" />&nbsp;'
		}else{
			html += '<img src="images/file.png" align="absmiddle" />&nbsp;'
		}
		
		if(is_dir){
			html+= '<a href="#" onclick="explore(\'' + btoa(list.files[i].ptr.pack()) + '\')">' + list.files[i].meta['name'] + '</a></td>';
		}else{
			html += '<a href="#" onclick="explore_file(\'' + btoa(list.files[i].ptr.pack()) + '\', \''+btoa(JSON.stringify(list.files[i].meta))+'\')">' + list.files[i].meta['name'] + '</a></td>';
		}
   		
   		
   		if(is_dir)
   			html += '<td></td><td></td>'
   		else
   			html += '<td>'+ format_size(list.files[i].meta['size']) + '</td><td>' + list.files[i].meta['type'] + '</td>'
   		
   		html += '<td align="right">'
   		
   		if(is_dir){
   			html += '<a href="#" onclick="ifs_explorer_rm(\''+list.files[i].meta['name']+'\', true)"><img src="images/cross.png" border="0" /></a>'
   		}else{
   			html += '<a href="'+ store.static_url(list.files[i].ptr, list.files[i].meta['type']) +'" title="Download"><img src="images/download.png" border="0" /></a>&nbsp;&nbsp;'
   			html += '<a href="#" onclick="ifs_explorer_rm(\''+list.files[i].meta['name']+'\', false)"><img src="images/cross.png" border="0" /></a>'
		}
		
		html += '</td></tr>'
   	}
   	html += '</table>'
   	return html;
}
   
function display_meta_data(obj){
	var html = []
	
	for (var key in obj)
  		html.push( '<b>' + key + '</b> = ' + obj[key]);
  		
  	
  	$('#blob_info').html(html.join(', '));
}	



